package org.jash.apps.model

import androidx.lifecycle.viewModelScope
import io.virtualapp.hook_sdk.app.InstallAppUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.jash.apps.net.AppService
import org.jash.common.log.logDebug
import org.jash.common.mvi.BaseState
import org.jash.common.mvi.BaseViewModel
import org.jash.common.net.retrofit
import java.io.FileOutputStream

class AppViewModel:BaseViewModel<AppIntent, AppState>() {
    val service: AppService by lazy { retrofit.create(AppService::class.java) }
    val installAppUtils by lazy { InstallAppUtils() }
    var cancel = false
    fun loadApps(loadApps: AppIntent.LoadApps) {
        viewModelScope.launch {
            state.value = try {
                val apiRes = service.getApps(mapOf("userId" to loadApps.userId, "page" to 1))
                if (apiRes.statusCode == 200) {
                    AppState.Response(apiRes.data)
                } else {
                    BaseState.Error(apiRes.msg)
                }
            } catch (e:Exception) {
                BaseState.Error(e.message ?: "")
            }
        }
    }
    fun downloadApp(down:AppIntent.DownloadApp) {
        logDebug(down.path.absolutePath)
        cancel = false
        if (!down.path.exists()) {
            viewModelScope.launch(Dispatchers.IO) {
                try {
                    val body = service.download(down.url)
                    val total:Long = 4 shl 20
                    body.byteStream().use { input ->
                        FileOutputStream(down.path).use { output ->
                            var length:Int
                            var buffer = ByteArray(4 shl  10)
                            var count:Long = 0;
                            while (input.read(buffer).apply { length = this } != -1) {
                                if(cancel) {
                                    throw RuntimeException("用户取消")
                                }
                                output.write(buffer, 0, length)
                                count += length
                                logDebug("count: $count, total: $total")
                                state.value = AppState.DownProgress(1F * count / total)
                            }
                        }
                    }
                    if (installAppUtils.installApp(down.path.absolutePath)) {
                        state.value = AppState.DownComplete
                        if (down.path.exists()) {
                            down.path.delete()
                        }
                    } else {
                        if (down.path.exists()) {
                            down.path.delete()
                        }
                        state.value = BaseState.Error("安装失败")
                    }
                } catch (e:Exception){
                    e.printStackTrace()
                    if (down.path.exists()) {
                        down.path.delete()
                    }
                    state.value = BaseState.Error(e.message ?: "")
                }
            }
        } else {
            state.value = BaseState.Error("文件已存在: ${down.path.name}")
        }

    }
    fun cancel(c:AppIntent.CancelDownload) {
        cancel = true
    }
}